vulkan: Add an api to update multiple image regions
authorMatthias Clasen <mclasen@redhat.com>
Thu, 21 Sep 2017 17:42:57 +0000 (13:42 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 21 Sep 2017 17:42:57 +0000 (13:42 -0400)
Instead of doing multiple copy commands with a tiny buffer
for each glyph, we can just batch them all together. This
also avoids the issue of creating multiple barriers for the
same image.

gsk/gskvulkanimage.c
gsk/gskvulkanimageprivate.h

index 3e365516c55543f7ee86fd80ea985d8808f11f81..5ab2ae6d6ed3acc8328b756e6cc60ca485b21e6a 100644 (file)
@@ -148,8 +148,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
 
       command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
       vkCmdPipelineBarrier (command_buffer,
+#if 0
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+                            VK_PIPELINE_STAGE_TRANSFER_BIT,
+                            VK_PIPELINE_STAGE_TRANSFER_BIT,
                             0,
                             0, NULL,
                             self->before_buffer_barriers->len, (VkBufferMemoryBarrier *) self->before_buffer_barriers->data,
@@ -164,8 +168,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
     {
       VkCommandBuffer command_buffer = gsk_vulkan_uploader_get_copy_buffer (self);
       vkCmdPipelineBarrier (command_buffer,
+#if 0
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
                             0,
                             0, NULL,
                             self->after_buffer_barriers->len, (VkBufferMemoryBarrier *) self->after_buffer_barriers->data,
@@ -663,23 +671,68 @@ gsk_vulkan_image_upload_region (GskVulkanImage    *self,
                                 gsize              stride,
                                 gsize              x,
                                 gsize              y)
+{
+  gsk_vulkan_image_upload_regions (self, uploader, 1, (GskImageRegion[1]) {
+                                                       {
+                                                          .data = data,
+                                                          .width = width,
+                                                          .height = height,
+                                                          .stride = stride,
+                                                          .x = x,
+                                                          .y = y 
+                                                       } });
+}
+
+void
+gsk_vulkan_image_upload_regions (GskVulkanImage    *self,
+                                 GskVulkanUploader *uploader,
+                                 guint              num_regions,
+                                 GskImageRegion    *regions)
 {
   GskVulkanBuffer *staging;
   guchar *mem;
+  guchar *m;
+  gsize size;
+  gsize offset;
+  VkBufferImageCopy *bufferImageCopy;
+
+  size = 0;
+  for (int i = 0; i < num_regions; i++)
+    size += regions[i].width * regions[i].height * 4;
 
-  staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
+  staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, size);
   mem = gsk_vulkan_buffer_map (staging);
 
-  if (stride == width * 4)
-    {
-      memcpy (mem, data, stride * height);
-    }
-  else
+  bufferImageCopy = alloca (sizeof (VkBufferImageCopy) * num_regions);
+  memset (bufferImageCopy, 0, sizeof (VkBufferImageCopy) * num_regions);
+
+  offset = 0;
+  for (int i = 0; i < num_regions; i++)
     {
-      for (gsize i = 0; i < height; i++)
+      m = mem + offset;
+      if (regions[i].stride == regions[i].width * 4)
         {
-          memcpy (mem + i * width * 4, data + i * stride, width * 4);
+          memcpy (m, regions[i].data, regions[i].stride * regions[i].height);
         }
+      else
+        {
+          for (gsize r = 0; r < regions[i].height; i++)
+            memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4);
+        }
+
+      bufferImageCopy[i].bufferOffset = offset;
+      bufferImageCopy[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+      bufferImageCopy[i].imageSubresource.mipLevel = 0;
+      bufferImageCopy[i].imageSubresource.baseArrayLayer = 0;
+      bufferImageCopy[i].imageSubresource.layerCount = 1;
+      bufferImageCopy[i].imageOffset.x = regions[i].x;
+      bufferImageCopy[i].imageOffset.y = regions[i].y;
+      bufferImageCopy[i].imageOffset.z = 0;
+      bufferImageCopy[i].imageExtent.width = regions[i].width;
+      bufferImageCopy[i].imageExtent.height = regions[i].height;
+      bufferImageCopy[i].imageExtent.depth = 1;
+
+      offset += regions[i].width * regions[i].height * 4;
     }
 
   gsk_vulkan_buffer_unmap (staging);
@@ -694,24 +747,8 @@ gsk_vulkan_image_upload_region (GskVulkanImage    *self,
                           gsk_vulkan_buffer_get_buffer (staging),
                           self->vk_image,
                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                          1,
-                          (VkBufferImageCopy[1]) {
-                               {
-                                   .bufferOffset = 0,
-                                   .imageSubresource = {
-                                       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                                       .mipLevel = 0,
-                                       .baseArrayLayer = 0,
-                                       .layerCount = 1
-                                   },
-                                   .imageOffset = { x, y, 0 },
-                                   .imageExtent = {
-                                       .width = width,
-                                       .height = height,
-                                       .depth = 1
-                                   }
-                               }
-                          });
+                          num_regions,
+                          bufferImageCopy);
 
   gsk_vulkan_uploader_add_image_barrier (uploader,
                                          TRUE,
index 5f2cdf77c66f0c946722d0ecd6a9930694043e1a..3aa02634174dafbfe6b7b7b8a02be2efb5e4f709 100644 (file)
@@ -39,6 +39,20 @@ void                    gsk_vulkan_image_upload_region                  (GskVulk
                                                                          gsize                   stride,
                                                                          gsize                   x,
                                                                          gsize                   y);
+
+typedef struct {
+  guchar *data;
+  gsize width;
+  gsize height;
+  gsize stride;
+  gsize x;
+  gsize y;
+} GskImageRegion;
+
+void                    gsk_vulkan_image_upload_regions                 (GskVulkanImage         *image,
+                                                                         GskVulkanUploader      *uploader,
+                                                                         guint                   num_regions,
+                                                                         GskImageRegion         *regions);
 GskVulkanImage *        gsk_vulkan_image_new_for_framebuffer            (GdkVulkanContext       *context,
                                                                          gsize                   width,
                                                                          gsize                   height);